package com.factory.code.controller;


import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ZipUtil;
import com.factory.code.common.helper.FilePathHelper;
import com.factory.code.controller.param.GeneratorCodeParam;
import com.factory.code.controller.vo.R;
import com.factory.code.service.TemplateService;
import com.factory.code.service.model.CodeFileModel;
import com.factory.code.service.model.TreeNodeModel;
import com.factory.code.service.model.ZipFileModel;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@RestController
@RequestMapping("generator")
@Api(tags = "生成代码 管理")
public class GeneratorController {
    @Autowired
    private TemplateService templateService;

    @ApiOperation(value = "生成代码")
    @SneakyThrows
    @PostMapping("generate")
    public R<Object> generate(@RequestBody GeneratorCodeParam param) {
        if (param.getProjectId() == null || param.getTableNames() == null || param.getTemplateIds() == null) {
            return R.fail("参数异常");
        }

        String batchNo = "CodeFactory_" + DateFormatUtils.format(new Date(), "yyyy_MM_dd_HH_mm_ss");

        List<CodeFileModel> files = templateService.getTableCodeByNames(param);
        String downloadPath = getDownloadPath() + batchNo + File.separator;
        for (CodeFileModel file : files) {
            String path = downloadPath + file.getFilePath() + File.separator + file.getFileName();
            String format = FilePathHelper.getSystemPathFormat(path);
            FileUtils.write(new File(format), file.getContent(), StandardCharsets.UTF_8);
        }

        File zip = ZipUtil.zip(downloadPath);
        ZipFileModel zipFileModel = new ZipFileModel();
        zipFileModel.setBatchNo(batchNo);
        zipFileModel.setDirectoryPath(downloadPath);
        zipFileModel.setZipPath(zip.getPath());
        return R.ok(zipFileModel);
    }

    private void zipWrite(HttpServletResponse response, List<CodeFileModel> tableCodeByNames) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        for (CodeFileModel model1 : tableCodeByNames) {
            zip.putNextEntry(new ZipEntry(model1.getFileName()));
            IOUtils.write(model1.getContent(), zip, "UTF-8");
            zip.closeEntry();
        }
        IOUtils.closeQuietly(zip);
        byte[] data = outputStream.toByteArray();
        response.reset();
        response.setHeader("Content-Disposition", "attachment; filename=\"codeFactory.zip\"");
        response.addHeader("Content-Length", "" + data.length);
        response.setContentType("application/octet-stream; charset=UTF-8");
        IOUtils.write(data, response.getOutputStream());
    }

    @ApiOperation(value = "根据文件路径查看内容")
    @SneakyThrows
    @GetMapping("/content")
    public R<Object> content(String filePath) {
        if (!FileUtil.exist(filePath) || FileUtil.isDirectory(filePath)) {
            return R.fail("file not exists");
        }
        String content = FileUtil.readString(new File(filePath), StandardCharsets.UTF_8);
        return R.ok(content);
    }

    @ApiOperation(value = "下载文件")
    @SneakyThrows
    @GetMapping("/download")
    public R<Object> downLoad(String batchNo, HttpServletResponse response) {
        String downloadPath = getDownloadPath();
        String filePath = downloadPath.concat(batchNo).concat(".zip");
        File file = new File(filePath);
        if (!file.exists()) {
            return R.fail("file not exists");
        }
        download(response, file);
        return R.ok("success");
    }

    @ApiOperation(value = "文件目录结构")
    @GetMapping("/tree")
    public R<TreeNodeModel> tree(String batchNo) {
        String downloadPath = getDownloadPath();
        String filePath = downloadPath.concat(batchNo);
        return R.ok(FilePathHelper.tree(filePath));
    }

    public static String getDownloadPath() {
        return FilePathHelper.getDownloadPath();
    }

    @SneakyThrows
    public File zip(List<CodeFileModel> tableCodeByNames) {
        FileUtil.del(new File(getDownloadPath()));
        String path = getDownloadPath().concat(System.currentTimeMillis() + "/");
        for (CodeFileModel file : tableCodeByNames) {
            FileUtils.write(new File(path.concat(file.getFilePath() + "/" + file.getFileName())), file.getContent(), StandardCharsets.UTF_8);
        }
        File zip = ZipUtil.zip(path);
        return zip;
    }

    private void download(HttpServletResponse response, File file) throws IOException {
        response.setContentType("application/vnd.ms-excel;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        // response.setContentType("application/force-download");
        response.setHeader("Content-Disposition", "attachment;fileName="
                + java.net.URLEncoder.encode(file.getName(), "UTF-8"));
        byte[] buffer = new byte[1024];
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        try {
            OutputStream os = response.getOutputStream();
            fis = new FileInputStream(file);
            bis = new BufferedInputStream(fis);
            int i = bis.read(buffer);
            while (i != -1) {
                os.write(buffer);
                i = bis.read(buffer);
            }
        } finally {
            if (null != bis) {
                bis.close();
            }
            if (null != fis) {
                fis.close();
            }
        }
    }

}
